package com.itaming.lycheeframework.mybatisplus.autofill;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.core.handlers.StrictFill;
import com.itaming.lycheeframework.common.constant.FrameworkConstant;
import com.itaming.lycheeframework.mybatisplus.base.BaseEntity;
import com.itaming.lycheeframework.support.utils.CollectionUtil;
import com.itaming.lycheeframework.support.utils.LambdaUtil;
import lombok.RequiredArgsConstructor;
import org.apache.ibatis.reflection.MetaObject;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 默认数据填充处理器
 *
 * @author A.Ming
 */
@RequiredArgsConstructor
public class DefaultMetaObjectHandler implements MetaObjectHandler {

    /**
     * 自动填充提供者
     */
    protected final AutoFillProvider autoFillProvider;

    @Override
    public void insertFill(MetaObject metaObject) {
        doFill(true, metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        doFill(false, metaObject);
    }

    /**
     * 执行填充
     *
     * @param isInsert   是否为插入
     * @param metaObject 元数据对象
     */
    private void doFill(boolean isInsert, MetaObject metaObject) {
        // 默认填充字段
        List<StrictFill<?, ?>> fills = getDefaultFills(isInsert);

        // 外部提供的填充字段
        List<StrictFill<?, ?>> providedFills = getProvidedFills(isInsert);
        if (CollectionUtil.isNotEmpty(providedFills)) {
            fills.addAll(providedFills);
        }

        // 填充
        if (CollectionUtil.isEmpty(fills)) {
            return;
        }

        strictFill(isInsert, findTableInfo(metaObject), metaObject, fills);
    }

    /**
     * 获取默认填充字段
     *
     * @param isInsert 是否为插入
     * @return 填充字段列表
     */
    private List<StrictFill<?, ?>> getDefaultFills(boolean isInsert) {
        List<StrictFill<?, ?>> fills = new ArrayList<>();

        // 获取填充值
        Long currentUserId = autoFillProvider.getCurrentUserId();
        LocalDateTime now = LocalDateTime.now();
        Integer isDeleted = FrameworkConstant.NOT_DELETED;

        // 设置填充字段
        if (isInsert) {
            fills.add(StrictFill.of(LambdaUtil.getPropertyName(BaseEntity::getCreateUser), () -> currentUserId, Long.class));
            fills.add(StrictFill.of(LambdaUtil.getPropertyName(BaseEntity::getCreateTime), () -> now, LocalDateTime.class));
            fills.add(StrictFill.of(LambdaUtil.getPropertyName(BaseEntity::getUpdateUser), () -> currentUserId, Long.class));
            fills.add(StrictFill.of(LambdaUtil.getPropertyName(BaseEntity::getUpdateTime), () -> now, LocalDateTime.class));
            // 逻辑删除字段建议在数据库层面设置默认值，此处仅作为补充和兜底
            fills.add(StrictFill.of(LambdaUtil.getPropertyName(BaseEntity::getIsDeleted), () -> isDeleted, Integer.class));
        } else {
            fills.add(StrictFill.of(LambdaUtil.getPropertyName(BaseEntity::getUpdateUser), () -> currentUserId, Long.class));
            fills.add(StrictFill.of(LambdaUtil.getPropertyName(BaseEntity::getUpdateTime), () -> now, LocalDateTime.class));
        }

        return fills;
    }

    /**
     * 获取外部提供的填充字段
     *
     * @param isInsert 是否为插入
     * @return 填充字段列表
     */
    private List<StrictFill<?, ?>> getProvidedFills(boolean isInsert) {
        return isInsert ? autoFillProvider.getInsertFills() : autoFillProvider.getUpdateFills();
    }

}
